﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Security.Permissions;

using RemotingInterfaces;

namespace Model.Hero
{
    [Serializable]
    public class Feat : Base_Stats, INotifyPropertyChanged, ISerializable, IFeat
    {

        public static Converter<Feat, IFeat> IFeat_to_Feat_converter  = new Converter<Feat, IFeat>(Feat.ToBase);

        private String _Name;
        //private static int _feat_id_counter = 0;
        private int _feat_id;
        private int _feat_prereq_1, _feat_prereq_2, _feat_prereq_3;                

        //public double XP_Bonus; //increase XP earned by 1 + XP_Bonus
        //first strike allows for an unretaliated attack
        public int First_Strike { get; set; }
        //Riposte counters first strike based on the value of riposte
        public int Riposte { get; set; }
        //circumstances
        public bool Is_in_the_dark;
        //cooldown: when feat is used, it can be used again after _cooldown number of combat rounds.
        //_cooldown == 0 means a passive feat
        //_cooldown_count counts number of rounds since last use, when _cooldown == _cooldown_count it is ready
        private int _cooldown, _cooldown_counter;
        private bool _ready;

        //buff variables
        private Buff _buff; //applies this buff when used
        
        //ID skal med. ligger i database
        public Feat(String name, int cooldown) : this(name, cooldown, 0, 0, 0)
        { 
        }

        public Feat(String name, int cooldown, int prereq1, int prereq2, int prereq3)
        {
            //_feat_id = ++_feat_id_counter;
            _feat_prereq_1 = prereq1;
            _feat_prereq_2 = prereq2;
            _feat_prereq_3 = prereq3;
            _Name = name;
            _ready = true;
            _cooldown = cooldown;

            //hvor skal de stå???
            NotifyPropertyChanged("Cooldown");
            NotifyPropertyChanged("Passive");
        }

        public Feat() { } //empty ctor for serialization

        protected Feat(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new System.ArgumentNullException("info");
            Name = (String)info.GetValue("Name", typeof(String));
            //bliver sjovt at udfylde...
        }
        
        public static IFeat ToBase(Feat feat)
        {
            return feat;
        }

        public String Name
        {
            get { return _Name; }
            set
            {
                _Name = value;
                NotifyPropertyChanged("Name");
            }
        }

        public int ID
        {
            get { return _feat_id; }
        }

        public int Prereq_Feat_ID_1
        {
            get { return _feat_prereq_1; }
            set
            {
                _feat_prereq_1 = value;
            }
        }

        public int Prereq_Feat_ID_2
        {
            get { return _feat_prereq_2; }
            set
            {
                _feat_prereq_2 = value;
            }
        }

        public int Prereq_Feat_ID_3
        {
            get { return _feat_prereq_3; }
            set
            {
                _feat_prereq_3 = value;
            }
        }

        public bool Passive //Passive == true means a skill that is always available
        {
            get { return Cooldown == 0 ? true : false; }
        }

        public int Cooldown
        {
            get { return _cooldown; }            
        }

        //increment cooldown counter (should be done after the end of a round)
        public void Tick()
        {
            if (_cooldown_counter < _cooldown)
            {
                _cooldown_counter++;
                NotifyPropertyChanged("Cooldown_Count");
                NotifyPropertyChanged("Ready");
            }
        }

        public int Cooldown_Counter
        {
            get { return _cooldown_counter; }
            //use Ready or Tick() to set counter
        }

        //nok smartere med en binding til counter og en converter der laver sammenligning
        public bool Ready
        {
            get { return _cooldown == _cooldown_counter; }
            set
            {
                if (value)
                {
                    _cooldown_counter = _cooldown;
                    NotifyPropertyChanged("Ready");
                    NotifyPropertyChanged("Cooldown_Counter");
                }
            }
        }

        //use the feat
        public void Activate()
        {            
            _cooldown_counter = 0;
            NotifyPropertyChanged("Cooldown_Count");
            NotifyPropertyChanged("Ready");
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        public override String ToString()
        {
            return Name;
        }

        [SecurityPermission(SecurityAction.LinkDemand,
        Flags = SecurityPermissionFlag.SerializationFormatter)]
        public virtual void GetObjectData(
        SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new System.ArgumentNullException("info");
            //Console.WriteLine("GetObjectData in Skill");            
            info.AddValue("Name", Name);
        }
    }
}
